package org.apache.rmiloader.action;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

public class RmiReport {
	private final String REXCEPTION = "java.rmi.RemoteException";
	 /** Logger Initialization */
    private Logger logger = Logger.getLogger(RmiReport.class);
    
	public long timeLoaded; //ms
	Set<RmiBean> rmiBeans;
	Set<Class<?>> rmiImpls;
	Set<Class<?>> rmiAbstracts;
	private HashMap<String, Class<?>> rmiMap;
	private HashMap<Class<?>, Class<?>> child2parent;
	
	
	private static RmiReport inst = null;
	
	public static synchronized RmiReport getInstance()
	{
		if (inst == null) {
			inst = new RmiReport();
			inst.timeLoaded = 0;
			inst.rmiMap = new HashMap<String, Class<?>>();
			inst.rmiBeans = null;
		}
		return inst;
	}
	
	public void setClassImpl(Set<Class<?>> list) {
		rmiImpls = list;
		for (Class<?> impl : rmiImpls) {
			rmiMap.put(impl.getName(), impl);
		}
	}
	
	public void setClassAbstract(Set<Class<?>> list) {
		rmiAbstracts = list;
	}

	public void setChild2Parent(HashMap<Class<?>, Class<?>> child2parent) {
		this.child2parent = child2parent;
	}

	// Get only rmi method implementation
		private List<String> getRmiMethods(String className) {
			List<String> list = new ArrayList<String>();
		
			//get right RMI class from name
			Class<?> impl = rmiMap.get(className);
			logger.debug("Impl: " + impl.getName());
			
			// get method from abstract class name
			Class<?> it = child2parent.get(impl);
			logger.debug("It: " + it.getName());
			
			for (Method mt : it.getMethods()) {
				for (Class<?> exp : mt.getExceptionTypes()) {
					logger.debug("exp: " + exp.getName());
					if (exp.getName().equals(REXCEPTION)) {
						list.add(mt.getName());
						break ;
					}
				}
			}
			return list;
		}
		
	// MODEL FOR STRUTS2 MVC
	public String getLoadingTime()
	{
		SimpleDateFormat sdf = new SimpleDateFormat("mm:ss:SS");
		 
		Date resultdate = new Date(timeLoaded);
		return sdf.format(resultdate);
	}
	
	public Set<RmiBean> getRmiBeans() {
		if (rmiBeans == null) {
			rmiBeans = new HashSet<RmiBean>();
			for (Class<?> impl : rmiImpls) {
				RmiBean elt = new RmiBean();
				elt.className = impl.getName();
				elt.methodNames = getRmiMethods(impl.getName());
				logger.debug("[RMIBEAN] " + elt.toString());
				rmiBeans.add(elt);
			}
		}
		return rmiBeans;
	}
}
